package org.nobject.common.file;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

/**
 * XML工具类
 * 
 * @author bianrongjun
 * @version 1.0
 */
public class XMLUtils {

	/** 
	 * 创建XML文档
	 * @param filepath 文件路径
	 * @param document 文档内容
	 */
	public static File makeDocument(String filepath, Document document) {
		return FileUtils.makeFile(filepath, format(document, null));
	}
	
	/**
	 * String str = "<package seqserial=\"1\" seqno=\"467\"><process processid=\"0021-W-20081209-00000005\" processstatus=\"7\" processdate=\"2008-12-09\" processtime=\"16:43:59\" processtype=\"1\" businesstype=\"1\" cfmmcreturncode=\"0\" cfmmcreturnmsg=\"数据格式检查完成;客户身份人工验证成功;\" exreturncode=\"\" exreturnmsg=\"\"><organ_info clienttype=\"2\" futuresid=\"00000151\" exchangeid=\"Z\" companyid=\"0021\" excompanyid=\"0195\" exclientidtype=\"3\" exclientid=\"\" clientname=\"恒生\" nocid=\"78345679-2\" licenseno=\"456\" compclientid=\"xc546\" organtype=\"110\" taxno=\"5678904567890345\" registrycapital=\"4564564\" legalperson=\"大范甘迪\" classify=\"020202\" contactperson=\"地方\" phone_countrycode=\"86\" phone_areacode=\"21\" phone_number=\"34545645\" addr_zipcode=\"200434\" addr_country=\"中国\" addr_province=\"156110000\" addr_address=\"法国德国\" auth_name=\"徐澄\" auth_idtype=\"1\" auth_id=\"310109198311074536\" auth_phone_countrycode=\"86\" auth_phone_areacode=\"21\" auth_phone_number=\"65928367\" auth_addr_zipcode=\"200434\" auth_addr_country=\"中国\" auth_addr_province=\"156120000\" auth_addr_address=\"风光好\" order_name=\"的法国德国\" order_idtype=\"1\" order_id=\"310109198311074536\" order_phone_countrycode=\"86\" order_phone_areacode=\"21\" order_phone_number=\"65928367\" order_addr_zipcode=\"200434\" order_addr_country=\"中国\" order_addr_province=\"156120000\" order_addr_address=\"风光好\" fund_name=\"发给回复\" fund_idtype=\"1\" fund_id=\"310109198311074536\" fund_phone_countrycode=\"86\" fund_phone_areacode=\"21\" fund_phone_number=\"65928367\" fund_addr_zipcode=\"200434\" fund_addr_country=\"中国\" fund_addr_province=\"156120000\" fund_addr_address=\"风光好\" bill_name=\"公交卡\" bill_idtype=\"1\" bill_id=\"310109198311074536\" bill_phone_countrycode=\"86\" bill_phone_areacode=\"21\" bill_phone_number=\"65928367\" bill_addr_zipcode=\"200434\" bill_addr_country=\"中国\" bill_addr_province=\"156120000\" bill_addr_address=\"风光好\" addr_city=\"156110103\" auth_addr_city=\"156120107\" order_addr_city=\"156120107\" fund_addr_city=\"156120107\" bill_addr_city=\"156120107\"><bankacc_list><bankacc accountname=\"恒生\" bankid=\"03\" accountno=\"3456789345678903\" branchname=\"水电费是否45678903\" branchname=\"随碟附送\"/></bankacc_list><businessrange_list><businessrange industryid=\"100104123172\"/></businessrange_list></organ_info></process></package>";
	 * format(str);
	 */
	
	/**
	 * 格式化XML
	 * @param doc DOC
	 * @param encoding 编码
	 */
	public static String format(Document doc, String encoding) {
		if (encoding == null) encoding = doc.getXMLEncoding();
		StringWriter writer = new StringWriter();
		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding(encoding);
		XMLWriter xmlwriter = new XMLWriter(writer, format);
		try {
			xmlwriter.write(doc);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		return writer.toString();
	}

	/**
	 * 校验
	 * @param path 路径
	 */
	public static boolean validate(String path) {
		File file = new File(path);
		if (file.exists()) {
			SAXReader reader = new SAXReader();
			reader.setValidation(true);
			try {
				reader.read(file);
				return true;
			} catch (DocumentException e) {
				return false;
			}
		}
		throw new RuntimeException("未找到文件:"+path);
	}

	/******************************************************************************************************************
	 * 
	 *  Element 区域
	 * 
	 *******************************************************************************************************************/
	
	/**
	 * 转字节到Element
	 * @param str 字符串
	 */
	public static Element toElement(String str) {
		try {
			return DocumentHelper.parseText(str).getRootElement();
		} catch (DocumentException e) {
			throw new RuntimeException(e);
		}
	}
	
	/******************************************************************************************************************
	 * 
	 *  Document 区域
	 * 
	 *******************************************************************************************************************/
	
	/** 
	 * 读取Document
	 * @param inputStream 输入流
	 */
	public static Document readDocument(InputStream inputStream) {
		return readDocument(inputStream, false);
	}
	
	/** 
	 * 读取Document
	 * @param inputStream 输入流
	 * @param validate 是否校验
	 */
	public static Document readDocument(InputStream inputStream, boolean validate) {
		try {
			SAXReader reader = new SAXReader();
			reader.setValidation(validate);
			return reader.read(inputStream);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 读取Document
	 * @param path 路径
	 * @param validate 是否校验
	 */
	public static Document readDocument(String path, boolean validate) {
		try {
			SAXReader reader = new SAXReader();
			reader.setValidation(validate);
			return reader.read(path);
		} catch (DocumentException e) {
			throw new RuntimeException(e);
		}
	}

	/** 
	 * 读取Document
	 * @param path
	 */
	public static Document readDocument(String path) {
		return readDocument(path,false);
	}
	
	/**
	 * 字符串转换为Document
	 * @param str 字符串
	 */
	public static Document toDocument(String str) {
		try {
			return DocumentHelper.parseText(str);
		} catch (DocumentException e) {
			throw new RuntimeException(e);
		}
	}
	
	/** 组合元素 */
	public static Element composeElement(Element copytoEle,Element sourceEle){
		List l=sourceEle.selectNodes("*");
		for (int i = 0; i < l.size(); i++) copytoEle.add(((Element) l.get(i)).createCopy());
		return copytoEle;
	}
	
	/** 
	 * ce
	 * @param pEle
	 * @param tagName
	 * @param atrVals
	 * @return
	 */
	public static Element ce(Element pEle,String tagName,String[][] atrVals){
		Element e=DocumentHelper.createElement(tagName);
		if(pEle!=null) pEle.add(e);
		setAtrVal(e, atrVals);
		return e;
	}
	
	/** 
	 * add
	 * @param pEle
	 * @param tagName
	 */
	public static Element ce(Element pEle,String tagName){
		return ce(pEle, tagName, null);
	}
	
	/** 
	 * ce
	 * @param tagName
	 * @param atrVals
	 * @return
	 */
	public static Element ce(String tagName,String[][] atrVals){
		return ce(null, tagName, atrVals);
	}
	
	/** 
	 * setAtrVal
	 * @param e
	 * @param atrVals
	 */
	public static void setAtrVal(Element e,String[][] atrVals){
		if(atrVals==null) return;
		for(String[] atrVal:atrVals){
			e.addAttribute(atrVal[0], atrVal[1]);
		}
	}
	
	/**
	 * format
	 * 
	 * @param doc
	 * @return
	 */
	public static String format(String xml) {
		return format(toDocument(xml), null);
		
		// byte []bs=xml.getBytes();
		// ByteBuffer bb=new ByteBuffer();
		// String stat=null;//{start:1,head:2,doctype:3,end:99}
		// int lev=0;
		// boolean tagBegin=false;
		// boolean headBegin=false;
		// boolean end=false;
		// for (int i = 0; i < bs.length; i++) {
		// if(stat==null){//未开始
		// if(bs[i]=='<'){
		// bb.append(bs[i]);
		// stat="XML";
		// lev++;
		// }
		// }else if(stat=="XML"){//开始
		// if(!tagBegin){
		// if(bs[i]=='<'){
		// tagBegin=true;
		// }
		// }
		// if(bs[i]=='<'){
		// tagBegin=true;
		//					
		// bb.append("\n").append(StringUtils.getRepeatStrs("\t",
		// lev)).append(bs[i]);
		//
		// }else if(bs[i]=='?'){
		// bb.append(bs[i]);
		// if(stat=="XML"){
		// stat="XML.HEAD.BEGIN";
		// }else if(stat=="XML.HEAD.BEGIN"){
		// stat="XML.HEAD.END";
		// }else{
		// log.error("error stat when ?");
		// return null;
		// }
		// }else if(bs[i]=='!'){
		// bb.append(bs[i]);
		// if(stat=="XML"){
		// stat="XML.DOC.BEGIN";
		// }else if(stat=="XML.DOC.BEGIN"){
		// stat="XML.DOC.END";
		// }else{
		// log.error("error stat when ?");
		// return null;
		// }
		// }else if(bs[i]=='/'){
		//				
		// if(i+1<bs.length&&bs[i+1]=='>'){
		// lev--;
		// }
		// bb.append(bs[i]);
		//					
		// }else if(bs[i]=='>'){
		// if(bs[i-1]=='/') lev--;
		// bb.append(bs[i]);
		// end=true;
		// }else{
		// if(stat=="XML.HEAD.BEGIN")
		// bb.append(bs[i]);
		// }
		// }else if(stat=="XML.HEAD.BEGIN"){//开始
		//				
		// bb.append(bs[i]);
		//				
		// }else if(stat=="XML.HEAD.END"){//开始
		// bb.append(bs[i]);
		// }else if(stat=="XML.HEAD.BEGIN"){//开始
		//				
		// }else{
		// System.out.println(bs[i]);
		// }
		// }
		// //System.out.println(bb.byteString(" "));
		// return bb.toString();
		//return null;
	}
	
	
	
	/** 
	 * 转义
	 * @param text
	 */
	public static String escape(String text) {
		StringBuffer buffer=new StringBuffer();
		
        char[] block = null;
        int i;
        int last = 0;
        int size = text.length();

        for (i = 0; i < size; i++) {
            String entity = null;
            char c = text.charAt(i);

            switch (c) {
                case '<':
                    entity = "&lt;";

                    break;

                case '>':
                    entity = "&gt;";

                    break;

                case '&':
                    entity = "&amp;";

                    break;

                case '\t':
                case '\n':
                case '\r':

                    // don't encode standard whitespace characters
                    if (true) {
                        entity = String.valueOf(c);
                    }

                    break;

                default:

                    if ((c < 32) ) {
                        entity = "&#" + (int) c + ";";
                    }

                    break;
            }

            if (entity != null) {
                if (block == null) {
                    block = text.toCharArray();
                }

                buffer.append(block, last, i - last);
                buffer.append(entity);
                last = i + 1;
            }
        }

        if (last == 0) {
            return text;
        }

        if (last < size) {
            if (block == null) {
                block = text.toCharArray();
            }

            buffer.append(block, last, i - last);
        }

        String answer = buffer.toString();
        buffer.setLength(0);

        return answer;
    }
	
}
